﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using TrainSimulator.Interfaces;
using System.Drawing;

namespace TrainSimulator.Model.Track
{
    public abstract class TrackGeometry
    {
        protected ITrack Track { get; set; }
        public PointF StartPoint { get; set; }
        private PointF CenterPoint { get; set; }
        public PointF EndPoint { get; set; }
        private double Radius { get; set; }
        protected double Direction { get; set; }
        public double Orientation { get; set; }
        public Bitmap TrackImage { get; set; }
        public double EndAngle
        {
            get { return Direction + DegreeToRadian(Orientation); }
        }

        public TrackGeometry(ITrack track, PointF startPoint, double direction, double orientation, Bitmap image)
        {
            this.Track = track;
            this.StartPoint = startPoint;
            this.Direction = direction;
            this.Orientation = orientation;
            this.TrackImage = image;
            this.Radius = Track.Length / DegreeToRadian(orientation);
            this.CenterPoint =  new PointF(
                    StartPoint.X - (float)(Radius * Math.Cos(direction)),
                    StartPoint.Y - (float)(Radius * Math.Sin(direction)));
            this.EndPoint = GetPosition(Track.Length); // Need centerpoint for position
        }

        public static TrackGeometry Create(ITrack track, PointF startPoint, double direction, double orientation, Bitmap trackImage)
        {
            TrackGeometry result = null;
            if (track.Angle != 0)
            {
                result = new CurveTrack(track, startPoint, direction, orientation, trackImage);
            }
            //else
            //{
            //    result = new StraightTrack(track, startPoint, direction, orientation, image);
            //}
            return result;
        }

        /// <summary>
        /// Returns the radian of a degree parameter.
        /// 
        /// An angle of 1 radian results in an arc with a 
        /// length equal to the radius of the circle.
        /// Read more: http://en.wikipedia.org/wiki/Radian
        /// </summary>
        public double DegreeToRadian(double deg)
        {
            return deg * Math.PI / 180;
        }
        /// <summary>
        /// Returns a degree of a radian parameter.
        /// </summary>
        public double RadianToDegree(double rad)
        {
            return rad * 180 / Math.PI;
        }

        public PointF GetPosition(double length)
        {
            PointF p = new PointF();
            double posAngle = GetAngle(length);
            p.X = CenterPoint.X + (float)(Radius * Math.Cos(posAngle));
            p.Y = CenterPoint.Y + (float)(Radius * Math.Sin(posAngle));
            return p;
        }
        public double GetAngle(double length)
        {
            return Direction + length / Radius;
        }
    }
}
